<?php
/**
 * Created by PhpStorm. User: ADun, Date: 14-10-7 上午10:27
 * Description:
 */
//TODO 此函数来自WE7 需要优化
    function LHmessage($msg, $redirect = '', $type = '') {
        print_r($msg);
    }
/*
function Encoding($file_name){
    if('WINNT' == PHP_OS)
        return mb_convert_encoding($file_name,'GB18030');
    return $file_name;
}
*/
function Encoding($file_name){
    if('WINNT' == PHP_OS)
        return mb_convert_encoding($file_name,'GB18030','UTF-8');
    return $file_name;
}
//写入浏览次数与浏览人数
function article_statistic($type,$uid,$tid){
    $type = intval($type);
    $tid = intval($tid);
    $openId = $_SESSION['vo用户数据']['openID'];
    switch($type){
        case 1:
            pdo()->update("`病历文章` set `浏览次数`=`浏览次数`+1",array(),array('id'=>$tid));
            break;
        case 2:
            pdo()->update("`语音课程` set `浏览次数`=`浏览次数`+1",array(),array('id'=>$tid));
            break;
    }
    $sql = "insert IGNORE into statistic(`type`,`uid`,`tid`,`time`, `openId`) VALUES($type,".intval($uid).",".$tid.",".time().",'".$openId."')";
    pdo()->exec($sql);
}
class Tools{
    public static $con;
    static function unicode2utf8_2($str) {
        $str = '{"result_str":"' . $str . '"}';
        $strarray = json_decode ( $str, true );
        return $strarray ['result_str'];
    }

    /**
     * @param $objectFrom
     * @param $objectTo
     * @return bool
     */
    static function objectCopy($objectFrom,$objectTo)
    {
        foreach ($objectTo as $k => $v) {
            foreach ($objectFrom as $k2 => $v2) {
                if ($k2 == $k) $objectTo->$k = $v2;
            }
        }
        return true;
    }


    static function array2string($array){
        return json_encode($array);
    }
    static function string2array($str)
    {
        $obj=json_decode($str);


        return self::object2array($obj);
    }

    /**
     * @根据公众号id获取公众号appid
     */
    static public function fh通过公众号id获取公众号appid($公众号id) {
        $pdo = pdo();
        $公众号 = $pdo -> selectColumns('public_serv_accounts',array('app_id'),array('id'=>$公众号id));
        return $公众号['app_id'];
    }
    static public function fh通过公众号id获取公众号详细信息($公众号id) {
        $pdo = pdo();
        /** @var  $公众号 DoPublic_serv_accounts */
        $Do公众号 = new DoPublic_serv_accounts();
        $公众号 = $pdo ->selectBO($Do公众号,array('id'=>$公众号id));
        return $公众号;
    }

    static public function fh通过公众号id获取公众号Token信息($公众号id) {
//        $pdo = pdo();
//        /** @var  $公众号 DoPublic_serv_accounts */
//        $Do参数 = new DoUniversalparameters();
//        $公众号参数 = $pdo -> selectColumns('UniversalParameters',array('value'),array('公众号id'=>$公众号id,'name'=>'AccessToken'));
//        return $公众号参数['value'];
       $公众号openID = pdo()->selectColumns('public_serv_accounts',array('公众号openID'),array('id'=>$公众号id));
        return self::getAccessToken($公众号id,$公众号openID['公众号openID']);
    }

    private static function getAccessTokenOld($公众号ID)
    {
        $do=new DoUniversalParameters();
        $ret = pdo()->selectBO($do,array('name'=>'AccessToken','公众号ID'=>$公众号ID));
        if($ret) return $do;
        return false;
    }

    private static function getAccessToken($公众号ID,$公众号openID)
    {
        $curTime = time();
        $公众号 = pdo()->selectColumns('public_serv_accounts',array('app_id','AppSecret'),array('id'=>$公众号ID));
        $公众号appid = $公众号['app_id'];
        $公众号appsecret = $公众号['AppSecret'];
        //如果没有AccessToken记录则 从wx取得一个，并记录到数据库

        if (!$voParameters =self::getAccessTokenOld($公众号ID)) {
            // echo "Token record not found!";

            $newToken = self::getAccessTokenNew($公众号appid,$公众号appsecret);
            if (!$newToken) {
                return false;
            }

            //todo accessToken 的取值和保存需要优化

            $voParameters=new DoUniversalParameters();
            $voParameters->set_value($newToken);
            $voParameters->set_name('AccessToken');
            $voParameters->set_公众号ID($公众号ID);
            $voParameters->set_公众号openID($公众号openID);

            $rst = $voParameters->save();

            //updated token record, current time will be updated automatically by DB
            if ($rst)
                return $newToken;
            else {
                return FALSE;
            }
        }

        $lastTime = strtotime($voParameters->get_update_time());
        $token = $voParameters->get_value();
        $interval = $curTime - $lastTime;

        // 小于微信规定的7200秒时间间隔，则返回当前access token，否则从微信服务器读取新的AccessToken，并记录到本地
        if ($interval < G_TOKEN_TIME) {
            return $token;
        } else {
            $newToken = self::getAccessTokenNew($公众号appid,$公众号appsecret);
            if (!$newToken) {
                return false;
            }

            if (self::updateToken($newToken,$公众号ID))
                return $newToken;
            else
                return FALSE;
        }
    }

    public static function getAccessTokenNew($公众号AppId,$公众号AppSecret)
    {
        $appId = $公众号AppId;
        $secret = $公众号AppSecret;

        $ret = file_get_contents('https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='.$appId.'&secret='.$secret);

        if (!$ret) {
            return false;
        }

        $decd = json_decode($ret);
        return $decd->access_token;
    }

    private static function updateToken($tkRecord,$公众号ID)
    {
        if (!$tkRecord) {
            return false;
        }
        $rst = pdo()->update('UniversalParameters',['update_time'=>date('Y-m-d H:i:s',time()),'value'=>$tkRecord],['name'=>'AccessToken','公众号Id'=>$公众号ID]);

        if (!$rst) {
            return false;
        } else {
            return true;
        }
    }
    /**
     * @param $array
     * @param $object //output
     * @return bool
     */
    static function array2object($array,$object)
    {
        if (!$array) return false;
        foreach ($object as $key => $value) {
            if (array_key_exists($key, $array))
                $object->$key = $array[$key];
        }
        return true;
    }

    /**
     * @param object $stdclassobject
     * @return string[]
     */
    static function object2array($stdclassobject)
    {
        $_array = is_object($stdclassobject) ? get_object_vars($stdclassobject) : $stdclassobject;

        $array=array();
        foreach ($_array as $key => $value) {

            $value = (is_array($value) || is_object($value)) ? Linhe::tools()->object2array($value) : $value;
            if($value)   $array[$key] = $value;
        }

        return $array;
    }
    function lhEncode($input){
        return urlencode(json_encode($input));
    }
    function lhDecode($input){
        return json_decode(urldecode($input));
    }
    //Http get post
    static function curl_get_contents($url,$timeout=4) {
        $curlHandle = curl_init();
        curl_setopt( $curlHandle , CURLOPT_URL, $url );
        curl_setopt( $curlHandle , CURLOPT_RETURNTRANSFER, 1 );
        curl_setopt( $curlHandle , CURLOPT_TIMEOUT, $timeout );
        $result = curl_exec( $curlHandle );
        curl_close( $curlHandle );
        return $result;
    }

    static function curl_get_contents2($url,$timeout=3) {
        $ch = curl_init();
        curl_setopt( $ch , CURLOPT_URL, $url );
        curl_setopt( $ch , CURLOPT_RETURNTRANSFER, 1 );
       // curl_setopt( $ch, CURLOPT_NOBODY, true);
       // curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, 'GET');
        curl_setopt( $ch , CURLOPT_TIMEOUT, $timeout );
        $result = curl_exec( $ch );
        curl_close( $ch );
        return $result;
    }
    static function curl_post_page($url,$data,$timeout=3){
        //$url = "http://localhost/web_services.php";
        //$post_data = array ("username" => "bob","key" => "12345");


        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_TIMEOUT, $timeout );
        // post数据
        curl_setopt($ch, CURLOPT_POST, 1);
        // post的变量
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        $output = curl_exec($ch);
        curl_close($ch);
        return $output;
    }


    public function curl_post_page_新($url, $data, $timeout = 4)
    {

        $ch = curl_init();
        curl_setopt($ch,CURLOPT_URL,$url);
        curl_setopt($ch,CURLOPT_CUSTOMREQUEST,"POST");
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
        curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);
        curl_setopt($ch,CURLOPT_AUTOREFERER,1);
        curl_setopt($ch,CURLOPT_POSTFIELDS,$data);
        curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
        $output = curl_exec($ch);
        if(curl_errno($ch)){
            echo curl_error($ch);
        }
        return $output;
    }


    public function curl_get_page_新($url){

        //初始化

        $ch = curl_init();

        //设置选项，包括url

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE);
        curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,FALSE);
        curl_setopt($ch,CURLOPT_FOLLOWLOCATION,1);
        curl_setopt($ch,CURLOPT_AUTOREFERER,1);
        curl_setopt($ch, CURLOPT_HEADER, 0);

        //执行并获取html内容

        $output = curl_exec($ch);

        //释放curl句柄

        curl_close($ch);

        return $output ;
    }


    function f生成文件($新文件名,$原二进制){
        $fh = fopen($新文件名, 'w');

        if ($fh) {
            fwrite($fh, $原二进制);
            fclose($fh);
           // exec("chmod -R 777 ".$新文件名);
            return  true;
        } else {
            return false;
        }
    }


    //TODO 传递openID(或者user Id)后可以不用通过微信转发通道
    static function GetTransmitUrl( $vs链接, $公众号AppId,$公众号Id)
    {
        $get = $_GET;
        unset($get['state']);

        $param = json_encode($get);
        $url = G_SITE_BASE."/business/wxtunnel.php?appid=".G_SERV_ID."&param=".$param;

        $url=urlencode($url);

        if (is_array($vs链接)) //如果是传多个参数
            $state = "000" . urlencode(json_encode($vs链接));
        else
            $state = $vs链接;

        $echo = $wxUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$公众号AppId}&redirect_uri={$url}&response_type=code&scope=snsapi_base&state={$state}#wechat_redirect";
;
        return  $echo;
    }

    static function pack参数打包($vs页面名称,array $va参数=null){
        if(is_null($va参数)){
            $state=$vs页面名称;
        }else{
            $va=array();
            $va[]=$vs页面名称;
            foreach($va参数 as $k=>$v){
                $va[$k]=$v;
            }
            $state = "000" . urlencode(json_encode($va));
        }
        return $state;
    }
    //TODO 页面传参流程需要统一
    static function unpack参数解析($state){
        //某些页面要传多个参数时，需要通过state参数分解
        if(substr($state,0,3)=='000'){
            $enc=substr($state,3);
            //logger()->logDebug2($enc);
            $paramArray=json_decode(urldecode($enc));
            logger()->logDebug2($paramArray);
            $page = $paramArray[0];
        }else{
            $page=$state;
        }
    }
     static function new页面链接消息($pageName,$description='点击打开',$title='微直达',$vs公众号AppId,$公众号Id,$specialUrl=false){
        $vo新闻=new Cbo图文消息列表();
        $baseUrl = G_SITE_BASE.'/business/';
        if($specialUrl==false)
            $url = self::GetTransmitUrl( $pageName,$vs公众号AppId,$公众号Id);
        else
            $url=$specialUrl;

        $vo新闻->ft添加图文消息 ($title.'🔽', '', $url, ''); // 添加一条图文信息

        $pictureUrl = $baseUrl . 'img/logoRed2s.jpg';
        $vo新闻->ft添加图文消息($description, '点击查看详情', $url, $pictureUrl);
        return $vo新闻;
    }
    static function new链接消息($url,$description,$title='微直达'){

        return self::new页面链接消息('',$description,$title,$url);
    }
    static function newDirect链接消息($description,$page,$openId,$va参数=null,$title='微直达'){
        $state=self::pack参数打包($page,$va参数);
        $url=G_SITE_BASE.'/business/index.php?state='.$state.'&openId='.$openId;
        return self::new页面链接消息('',$description,$title,$url);
    }
    /**
     * 内部用函数：将数据存为文件(文件名自动编号)
     * @param string $path 存盘目录
     * @param string $data 要保存的数据
     */
    private function saveDataToFile($path, $data)
    {
        $fnum = 1;
        $filename = "data" . $fnum;
        while (file_exists($path . $filename)) {
            $fnum ++;
            $filename = "data" . $fnum;
        }
        $handle = fopen($path . $filename, "w");
        fwrite($handle, $data);
        fclose($handle);
    }

    static function url($m, $a, $param = array()) {
        $url = G_SITE_BASE . "/index.php?m=$m&a=$a";
        if ($param) {
            $q = http_build_query($param);
            $url = $url.'&'.$q;
        }
        return $url;
    }

    static function oss_url($file, $timeout = 3600) {
        require_once __DIR__ . '/../sdk/aliyun-oss-php-sdk-master/index.php';

        $bucket = AliyunOssCommon::getBucketName();
        $ossClient = AliyunOssCommon::getOssClient();
        if (is_null($ossClient)) return '';

        $signedUrl = $ossClient->signUrl($bucket, $file, $timeout);
        return $signedUrl;
    }

    static function upload_img($图片信息,$图片路径,$前置=null,$name=null){
        $文件目录 = G_LHDir.$图片路径;
        if (!$name) {
            $name = 'pic';
        }
        if (!empty($图片信息[$name]["name"])) { //提取文件域内容名称，并判断
            if(!file_exists($文件目录)) {
                //检查是否有该文件夹，如果没有就创建，并给予最高权限
                mkdir("$文件目录", 0777);
            }
            //允许上传的文件格式
            $tp = array('image/jpg','image/jpeg','image/png','image/pjpeg');

            //检查上传文件是否在允许上传的类型
            if(!in_array($图片信息[$name]["type"],$tp)) {
                return '文件上传类型错误!';
            }

            if($图片信息[$name]["size"]>10194304) {
                return '图片大小超过10M!';
            }

            $type = '.jpg';
            $today=date('YmdHis'); //获取时间并赋值给变量
            $file2 = $文件目录.$前置.$today.$type; //图片的完整路径
            $imgurl =$图片路径.$前置.$today.$type; //图片名称

            $result=move_uploaded_file($图片信息[$name]["tmp_name"],$file2);

            if($result) {
                return $imgurl;
            } else {
                return '图片上传失败';
            }
        }
        return '图片上传失败';
    }

    static function upload_imgs($File,$img_url,$name='pic',$前置=null) {
        // $name 为上传文件文本框的 name
        $文件目录 = G_LHDir.$img_url;
        $num=count($File[$name]["name"]);
        $multiurl=array();
        for($i=0;$i<$num;$i++){
            if ($File[$name]["name"][$i]!=null) { //提取文件域内容名称，并判断
                if(!file_exists($文件目录))
                {
                    //检查是否有该文件夹，如果没有就创建，并给予最高权限
                    mkdir("$文件目录", 0777);
                }
                //允许上传的文件格式
                $tp = array('image/jpg','image/jpeg','image/png','image/pjpeg');

                //检查上传文件是否在允许上传的类型
                if(!in_array($File[$name]["type"][$i],$tp))
                {
                    return '文件上传类型错误!';
                }

                if($File[$name]["size"][$i]>20971520) {
                    return '图片大小超过20M!';
                }
                $filetype = $File[$name]['type'][$i];
                if($filetype == 'image/jpeg'){
                    $type = '.jpg';
                }
                if ($filetype == 'image/jpg') {
                    $type = '.jpg';
                }
                if ($filetype == 'image/pjpeg') {
                    $type = '.jpg';
                }
                if ($filetype == 'image/png') {
                    $type = '.jpg';
                }
                if($File[$name]["name"][$i])
                {
                    $today=date('YmdHis'); //获取时间并赋值给变量
                    $file2 = $文件目录.$前置.$i.$today.$type; //图片的完整路径
                    $imgurl =$img_url.$前置.$i.$today.$type; //图片名称
                    $result=move_uploaded_file($File[$name]["tmp_name"][$i],$file2);
                }//END IF
                $multiurl[]=$imgurl;

            }else {
                $multiurl[]="没有图片";
            }

        }
        return $multiurl;
    }
    static function File_Upload($file,$path){

        $max_file_size=10194304;

        $uptypes=array('image/jpeg','image/png','image/gif','image/jpg');

        if (!is_uploaded_file($file['tmp_name']))

        {
            echo "图片不存在!";
            exit;
        }
        if($max_file_size < $file["size"])
        {
            echo "文件太大!";
            exit;
        }

        if(!in_array($file["type"], $uptypes))

        {
            echo "文件类型不符!".$file["type"];
            exit;
        }

        if(!file_exists($path))
        {
            mkdir($path);
        }

        $filename=$file["tmp_name"];
        $pinfo=pathinfo($file["name"]);
        $ftype=$pinfo['extension'];

        $pathname=time().".".$ftype;

        $destination = $path."/".$pathname;

        $res=move_uploaded_file ($filename, $destination);
        $route = strrchr($path, '/');
        if($res)
        {
            return G_SITE_BASE."/cache".$route."/".$pathname;
        }

        return "图片上传失败";
    }

    //发送手机验证码
    static function send_text_messages($content, $tel) {
        $post_data = array();
        $post_data['userid'] = '6474';
        $post_data['password'] = 'qwer1234';
        $post_data['account'] ='a10498';
        $post_data['content'] = $content;
      //  $post_data['content'] = $content. "仅本次有效，请勿转发或告知他人。";
        $post_data['mobile'] = $tel;
        $post_data['sendtime'] = '';
        $url='http://121.52.209.125:8888/sms.aspx?action=send';
        $o='';
        foreach ($post_data as $k=>$v) {
            $o.="$k=".urlencode($v).'&';
        }
        $post_data=substr($o,0,-1);
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        curl_setopt($ch, CURLOPT_URL,$url);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data);
        $result = curl_exec($ch);

        logger()->logInfo("发送短信给" . $tel. "，内容：". $content);
        return $result;
    }

    static function getIP() {
        if (getenv('HTTP_CLIENT_IP')) {
            $ip = getenv('HTTP_CLIENT_IP');
        } elseif (getenv('HTTP_X_FORWARDED_FOR')) { //获取客户端用代理服务器访问时的真实ip 地址
            $ip = getenv('HTTP_X_FORWARDED_FOR');
        } elseif (getenv('HTTP_X_FORWARDED')) {
            $ip = getenv('HTTP_X_FORWARDED');
        } elseif (getenv('HTTP_FORWARDED_FOR')) {
            $ip = getenv('HTTP_FORWARDED_FOR');
        } elseif (getenv('HTTP_FORWARDED')) {
            $ip = getenv('HTTP_FORWARDED');
        } else {
            $ip = $_SERVER['REMOTE_ADDR'];
        }
        return $ip;
    }

    //导出数据
    static function export($tablename,$data){
        require_once 'excle/excel.class.php';
        $xls= new excel('UTF-8',false,$tablename);


        $xls->addArray($data);
        $xls->generateXML($tablename);
    }

    static function checkPhone($phone) {
        if(preg_match("/^1[34578]{1}\d{9}$/", $phone)) {
            return true;
        }
        return false;
    }

    public static function upload_qiniu_pic($pic){
        require_once _LHDir . 'sdk/php-sdk-qiniu/autoload.php';
        // 引入鉴权类
        require_once _LHDir . 'sdk/php-sdk-qiniu/src/Qiniu/Auth.php';
        // 引入上传类
        require_once _LHDir . 'sdk/php-sdk-qiniu/src/Qiniu/Storage/UploadManager.php';
        // 需要填写你的 Access Key 和 Secret Key
        $accessKey = QIU_NIU_AK;
        $secretKey = QIU_NIU_SK;
        // 构建鉴权对象
        $auth = new \Qiniu\Auth($accessKey, $secretKey);

        // 要上传的空间
        $bucket = QIU_NIU_BUCKET;
        // 生成上传 Token
        $token = $auth->uploadToken($bucket);
        $realname = $_FILES[$pic]['name'];
        $arrFileInfo = pathinfo($realname);
        $extension = $arrFileInfo['extension'];
        // 要上传文件的本地路径
        $filePath = $_FILES[$pic]['tmp_name'];
        // 上传到七牛后保存的文件名
        $key = time().".".$extension;
        // 初始化 UploadManager 对象并进行文件的上传。
        $uploadMgr = new \Qiniu\Storage\UploadManager();
        // 调用 UploadManager 的 putFile 方法进行文件的上传。
        list($ret, $err) = $uploadMgr->putFile($token, null, $filePath);
        if ($err !== null) {
            return $err;
        } else {
            return $ret;
        }

    }

    //上传服务器的文件到七牛
    public static function upload_qiniu_fromServer($filePath) {
        require_once _LHDir . 'sdk/php-sdk-qiniu/autoload.php';
        // 引入鉴权类
        require_once _LHDir . 'sdk/php-sdk-qiniu/src/Qiniu/Auth.php';
        // 引入上传类
        require_once _LHDir . 'sdk/php-sdk-qiniu/src/Qiniu/Storage/UploadManager.php';
        // 需要填写你的 Access Key 和 Secret Key
        $accessKey = QIU_NIU_AK;
        $secretKey = QIU_NIU_SK;
        // 构建鉴权对象
        $auth = new \Qiniu\Auth($accessKey, $secretKey);

        // 要上传的空间
        $bucket = QIU_NIU_BUCKET;
        // 生成上传 Token
        $token = $auth->uploadToken($bucket);

        // 初始化 UploadManager 对象并进行文件的上传。
        $uploadMgr = new \Qiniu\Storage\UploadManager();
        // 调用 UploadManager 的 putFile 方法进行文件的上传。
        list($ret, $err) = $uploadMgr->putFile($token, null, $filePath);
        if ($err !== null) {
            return $err;
        } else {
            return QIU_NIU_PIC_URL . $ret['key'];
        }
    }

}

class HttpManager {
    protected $hasCurl;
    protected $useCurl;
    protected $useBasicAuth;
    protected $HTTPVersion;
    protected $host;
    protected $port;
    protected $uri;
    protected $type;
    protected $query;
    protected $timeout;
    protected $error;
    protected $response;
    protected $responseText;
    protected $responseHeaders;
    protected $executed;
    protected $fsock;
    protected $curl;
    protected $additionalCurlOpts;
    protected $authUsername;
    protected $authPassword;

    public function __construct($host = null, $uri = '/', $port = 80, $useCurl = null, $timeout = 5) {
        if (!$host) {
            return false;
        }
        $this -> hasCurl = function_exists('curl_init');
        $this -> useCurl = $this -> hasCurl ? ($useCurl !== null ? $useCurl : true) : false;
        $this -> type = 'GET';
        $this -> HTTPVersion = '1.1';
        $this -> host = $host ? $host : $_SERVER['HTTP_HOST'];
        $this -> uri = $uri;
        $this -> port = $port;
        $this -> timeout = $timeout;
        $this -> setHeader('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8');
        $this -> setHeader('Accept-Language', 'en-us,en;q=0.5');
        $this -> setHeader('Accept-Encoding', 'deflate');
        $this -> setHeader('Accept-Charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.7');
        $this -> setHeader('User-Agent', 'Mozilla/5.0 Firefox/3.6.12');
        $this -> setHeader('Connection', 'close');
        return $this;
    }

    public function setHeader($header, $content) {
        $this -> headers[$header] = $content;
        return $this;
    }

    public static function curlHeaders() {
        return array(
            'User-Agent' => CURLOPT_USERAGENT,
        );
    }

    public function setHost($host) {
        $this -> host = $host;
        return $this;
    }

    public function setRequestURI($uri) {
        $this -> uri = $uri;
        return $this;
    }

    // @TODO: Deprecate setGetData in preference of setQueryParams

    public function setPort($port) {
        $this -> port = $port;
        return $this;
    }

    public function setTimeout($timeout) {
        $this -> timeout = $timeout;
        return $this;
    }

    public function setGetData($get) {
        $this -> query = $get;
        return $this;
    }

    public function setQueryParams($get) {
        $this -> query = $get;
        return $this;
    }

    public function setUseCurl($use) {
        if ($use && $this -> hasCurl) {
            $this -> useCurl = true;
        } else {
            $this -> useCurl = false;
        }
        return $this;
    }

    public function setType($type) {
        if (in_array($type, array('POST', 'GET', 'PUT', 'DELETE'))) {
            $this -> type = $type;
        }
        return $this;
    }

    public function setData($data) {
        $this ->data = $data;
        return $this;
    }

    public function setUrl($url) {
        $this -> url = $url;
        return $this;
    }

    public function setAdditionalCurlOpt($option, $value) {
        if (is_array($option)) {
            foreach ($option as $opt => $val) {
                $this -> setAdditionalCurlOpt($opt, $val);
            }
        } else {
            $this -> additionalCurlOpts[$option] = $value;
        }
    }

    public function setUseBasicAuth($set, $username = null, $password = null) {
        $this -> useBasicAuth = $set;
        if ($username) {
            $this -> setAuthUsername($username);
        }
        if ($password) {
            $this -> setAuthPassword($password);
        }
    }

    public function setAuthUsername($username = null) {
        $this -> authUsername = $username;
    }

    public function setAuthPassword($password = null) {
        $this -> authPassword = $password;
    }

    public function execute() {
        if ($this -> useCurl) {
            $this -> curl_execute();
        } else {
            $this -> fsockget_execute();
        }
        $this->close();
        return $this;
    }

    protected function curl_execute() {
        $uri = $this -> uri;
        $host = $this -> host;
        $type = $this -> type;
        $port = $this -> port;

        //$data = property_exists($this, 'data') ? HTTPRequest::param($this -> data) : false;
        if(isset($this->data))		$data =$this -> data;
        $timeout = $this -> timeout;

        // Initiate cURL.
        $ch = curl_init();

        // Set request type.
        if ($type === 'GET') {
            curl_setopt($ch, CURLOPT_HTTPGET, true);
        } else if ($type === 'POST') {
            curl_setopt($ch, CURLOPT_POST, true);
            if ($data) {
                curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
            }
        } else if ($type === 'PUT') {
            curl_setopt($ch, CURLOPT_PUT, true);
        } else {
            curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $type);
        }

        // Grab query string.
        $query = property_exists($this, 'query') && $this -> query ? '?'.HttpManager::param($this -> query) : '';
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

        // Set additional headers.
        $headers = array();
        foreach ($this -> headers as $name => $val) {
            $headers[] = $name.': '.$val;
        }
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

        // Do stuff it it's HTTPS/SSL.
        if ($port == 443) {
            $protocol = 'https';
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
        } else {
            $protocol = 'http';
        }

        if (!empty($this -> additonalCurlOpts)) {
            foreach ($this -> additionalCurlOpts as $option => $value) {
                curl_setopt($ch, $option, $value);
            }
        }
        // Build and set URL.
        $url = $protocol.'://'.$host.$uri.$query;
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_PORT, $port);

        // Add any authentication to the request.
        // Currently supports only HTTP Basic Auth.
        if ($this -> useBasicAuth === true) {
            curl_setopt($ch, CURLOPT_USERPWD, $this -> authUsername.':'.$this -> authPassword);
            curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
        }

        // Execute!
        $rsp = curl_exec($ch);
        $this -> curl = $ch;
        $this -> executed = true;

        // Handle an error.
        if (!$error = curl_error($ch)) {
            $this -> response = array('responseText' => $rsp) + curl_getinfo($ch);
            $this -> responseHeaders = curl_getinfo($ch);
            $this -> responseText = $rsp;
        } else {
            $this -> error = $error;
        }
    }

    public function param($data) {
        $data_array = array();
        foreach ($data as $key => $val) {
            if (!is_string($val)) {
                $val = json_encode($val);
            }
            $data_array[] = urlencode($key).'='.urlencode($val);
        }
        return implode('&', $data_array);
    }

    protected function fsockget_execute() {
        $uri = $this -> uri;
        $host = $this -> host;
        $port = $this -> port;
        $type = $this -> type;
        $HTTPVersion = $this -> HTTPVersion;
        $data = property_exists($this, 'data') ? $this -> data : null;
        $crlf = "\r\n";

        $rsp = '';

        // Deal with the data first.
        if ($data && $type === 'POST') {
            $data = $this -> param($data);
        } else if ($data && $type === 'GET') {
            $get_data = $data;
            $data = $crlf;
        } else {
            $data = $crlf;
        }
        // Then add
        if ($type === 'POST') {
            $this -> setHeader('Content-Type', 'application/x-www-form-urlencoded');
            $this -> setHeader('Content-Length', strlen($data));
            $get_data = property_exists($this, 'query') && $this -> query ? HttpManager::param($this -> query) : false;
        } else {
            $this -> setHeader('Content-Type', 'text/plain');
            $this -> setHeader('Content-Length', strlen($crlf));
        }
        if ($type === 'GET') {
            if (isset($get_data)) {
                $get_data = $data;
            } else if ($this -> query) {
                $get_data = HttpManager::param($this -> query);
            }
        }
        if ($this -> useBasicAuth === true) {
            $this -> setHeader('Authorization', 'Basic '.base64_encode($this -> authUsername.':'.$this -> authPassword));
        }
        $headers = $this -> headers;
        $req = '';
        $req .= $type.' '.$uri.(isset($get_data) ? '?'.$get_data : '').' HTTP/'.$HTTPVersion.$crlf;
        $req .= "Host: ".$host.$crlf;
        foreach ($headers as $header => $content) {
            $req .= $header.': '.$content.$crlf;
        }
        $req .= $crlf;
        if ($type === 'POST') {
            $req .= $data;
        } else {
            $req .= $crlf;
        }

        // Construct hostname.
        $fsock_host = ($port == 443 ? 'ssl://' : '').$host;

        // Open socket.
        $httpreq = @fsockopen($fsock_host, $port, $errno, $errstr, 30);

        // Handle an error.
        if (!$httpreq) {
            $this -> error = $errno.': '.$errstr;
            return false;
        }

        // Send the request.
        fputs($httpreq, $req);

        // Receive the response.
        while ($line = fgets($httpreq)) {
            $rsp .= $line;
        }


        // Extract the headers and the responseText.
        list($headers, $responseText) = explode($crlf.$crlf, $rsp);

        // Store the finalized response.
        $this -> response = $rsp;
        $this -> responseText = $responseText;
        $this -> status = array_shift($headers);

        // Store the response headers.
        $headers = explode($crlf, $headers);
        $this -> responseHeaders = array();
        foreach ($headers as $header) {
            list($key, $val) = explode(': ', $header);
            $this -> responseHeaders[$key] = $val;
        }

        // Mark as executed.
        $this -> executed = true;

        // Store the resource2 so we can close it later.
        $this -> fsock = $httpreq;
        return true;
    }

    private function close() {
        if (!$this -> executed) {
            return false;
        }
        if ($this -> useCurl) {
            $this -> curl_close();
        } else {
            $this -> fsockget_close();
        }
        return false;
    }

    protected function curl_close() {
        curl_close($this -> curl);
    }

    protected function fsockget_close() {
        fclose($this -> fsock);
    }

    public function getError() {
        return $this -> error;
    }

    public function getResponse() {
        if (!$this -> executed) {
            return false;
        }
        return $this -> response;
    }

    public function getResponseText() {
        if (!$this -> executed) {
            return false;
        }
        return $this -> responseText;
    }

    public function getAllResponseHeaders() {
        if (!$this -> executed) {
            return false;
        }
        return $this -> responseHeaders;
    }

    public function getResponseHeader($header) {
        if (!$this -> executed) {
            return false;
        }
        $headers = $this -> responseHeaders;
        if (array_key_exists($header, $headers)) {
            return $headers[$header];
        }
        return false;
    }


}
